package com.study.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
 * 通过 nacos 下发动态路由配置、监听 nacos 中路由配置变更
 */
@Slf4j
@Component
@DependsOn({"gatewayConfig"})
public class DynamicRouteServiceImplByNacos {

    //nacos 配置服务
    private ConfigService configService;
    private final DynamicRouteServiceImpl dynamicRouteService;

    public DynamicRouteServiceImplByNacos(DynamicRouteServiceImpl dynamicRouteService) {
        this.dynamicRouteService = dynamicRouteService;
    }

    /**
     * bean在容器中构造完成之后会执行的init方法
     */
    @PostConstruct
    public void init(){

        log.info("gateway route init...");

        try {
            //初始化 nacos 配置客户端
            configService = initConfigService();
            if(configService == null){
                log.error("init config service fail");
                return;
            }

            //通过 nacos config 并指定路由配置路径去获取路由配置
            String configInfo = configService.getConfig(
                    GatewayConfig.NACOS_ROUTE_DATA_ID,
                    GatewayConfig.NACOS_ROUTE_GROUP,
                    GatewayConfig.DEFAULT_TIMEOUT);

            List<RouteDefinition> definitionList =
                    JSON.parseArray(configInfo, RouteDefinition.class);

            if(!CollectionUtils.isEmpty(definitionList)){
                for (RouteDefinition routeDefinition : definitionList) {
                    dynamicRouteService.addRouteDefinition(routeDefinition);
                }
            }

            dynamicRouteByNacosListner(GatewayConfig.NACOS_ROUTE_DATA_ID,
                    GatewayConfig.NACOS_ROUTE_GROUP);


        }catch (Exception e){
            log.error("gateway route init error: [{}]",e.getMessage(),e);
        }
    }

    //初始化nacos config
    private ConfigService initConfigService() {

        try {
            Properties properties = new Properties();
            properties.setProperty("serverAddr", GatewayConfig.NACOS_SERVER_ADDR);
            properties.setProperty("namespace", GatewayConfig.NACOS_NAMESPACE);
            return configService = NacosFactory.createConfigService(properties);
        } catch (Exception e) {
            log.error("初始化 gateway nacos config error: [{}]", e.getMessage(), e);
            return null;
        }
    }

    //监听 nacos下发的动态路由配置
    private void dynamicRouteByNacosListner(String dataId, String group) {

        try {

            //给nacos config 客户端增加一个监听器
            configService.addListener(dataId, group, new Listener() {

                /***
                 * 自己提供线程池执行操作
                 */
                @Override
                public Executor getExecutor() {
                    return null;
                }

                /**
                 *  监听器接收到配置更新
                 *  configInfo Nacos中最新的配置定义
                 */
                @Override
                public void receiveConfigInfo(String configInfo) {

                    log.info("开始更新config", configInfo);

                    List<RouteDefinition> definitionList = JSON.parseArray(configInfo, RouteDefinition.class);

                    dynamicRouteService.updateList(definitionList);
                }
            });
        } catch (Exception e) {
            log.error("动态更新 gateway config error: [{}]", e.getMessage(), e);
        }
    }
}
